<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <meta
      name="description"
      content="Point cloud of the city of Montreal, Canada captured in 2015 with a resolution of 20 cm. Tiled and hosted by Cesium ion."
    />
    <meta name="cesium-sandcastle-labels" content="ion Assets" />
    <title>Montreal Point Cloud</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script
      type="text/javascript"
      src="../../../Build/CesiumUnminified/Cesium.js"
      nomodule
    ></script>
    <script type="module" src="../load-cesium-es6.js"></script>
  </head>
  <body
    class="sandcastle-loading"
    data-sandcastle-bucket="bucket-requirejs.html"
  >
    <style>
      @import url(../templates/bucket.css);
      #toolbar {
        background: rgba(42, 42, 42, 0.8);
        padding: 4px;
        border-radius: 4px;
      }
      #toolbar input {
        vertical-align: middle;
        padding-top: 2px;
        padding-bottom: 2px;
      }
      #toolbar .header {
        font-weight: bold;
      }
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>
    <div id="toolbar">
      <table>
        <tbody>
          <tr>
            <td class="header">Classification Types</td>
          </tr>
          <tr>
            <td>Ground</td>
            <td><input type="checkbox" data-bind="checked: ground" /></td>
          </tr>
          <tr>
            <td>Low Vegetation</td>
            <td>
              <input type="checkbox" data-bind="checked: low_vegetation" />
            </td>
          </tr>
          <tr>
            <td>Medium Vegetation</td>
            <td>
              <input type="checkbox" data-bind="checked: medium_vegetation" />
            </td>
          </tr>
          <tr>
            <td>High Vegetation</td>
            <td>
              <input type="checkbox" data-bind="checked: high_vegetation" />
            </td>
          </tr>
          <tr>
            <td>Buildings</td>
            <td><input type="checkbox" data-bind="checked: buildings" /></td>
          </tr>
          <tr>
            <td>Other/Unclassified</td>
            <td><input type="checkbox" data-bind="checked: other" /></td>
          </tr>
        </tbody>
      </table>
    </div>
    <script id="cesium_sandcastle_script">
      function startup(Cesium) {
        "use strict";
        //Sandcastle_Begin
        const viewer = new Cesium.Viewer("cesiumContainer", {
          terrainProvider: Cesium.createWorldTerrain(),
        });

        // A ~10 billion point 3D Tileset of the city of Montreal, Canada captured in 2015 with a resolution of 20 cm. Tiled and hosted by Cesium ion.
        const tileset = viewer.scene.primitives.add(
          new Cesium.Cesium3DTileset({
            url: Cesium.IonResource.fromAssetId(28945),
            pointCloudShading: {
              attenuation: true,
              maximumAttenuation: 2,
            },
          })
        );

        // Fly to a nice overview of the city.
        viewer.camera.flyTo({
          destination: new Cesium.Cartesian3(
            1223285.2286828577,
            -4319476.080312792,
            4562579.020145769
          ),
          orientation: {
            direction: new Cesium.Cartesian3(
              0.63053223097472,
              0.47519958296727743,
              -0.6136892226931869
            ),
            up: new Cesium.Cartesian3(
              0.7699959023135587,
              -0.4824455703743441,
              0.41755548379407276
            ),
          },
          easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
        });

        // Add stored views around Montreal. You can add to this list by capturing camera.position, camera.direction and camera.up.
        Sandcastle.addToolbarMenu([
          {
            text: "Overview",
            onselect: function () {
              viewer.camera.flyTo({
                destination: new Cesium.Cartesian3(
                  1268112.9336926902,
                  -4347432.089579957,
                  4539129.813606778
                ),
                orientation: {
                  direction: new Cesium.Cartesian3(
                    -0.23288147105081208,
                    0.9376599248561527,
                    -0.25799241415197466
                  ),
                  up: new Cesium.Cartesian3(
                    -0.015748156073159988,
                    0.2616156268422992,
                    0.9650436567182887
                  ),
                },
                easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
              });
            },
          },
          {
            text: "Highway",
            onselect: function () {
              viewer.camera.flyTo({
                destination: new Cesium.Cartesian3(
                  1266560.143870489,
                  -4278126.842199712,
                  4542690.264566619
                ),
                orientation: {
                  direction: new Cesium.Cartesian3(
                    -0.3402460635871598,
                    -0.46669052711538217,
                    -0.8163532128400116
                  ),
                  up: new Cesium.Cartesian3(
                    0.08964012922691329,
                    -0.8802940231336787,
                    0.46588311846138497
                  ),
                },
                easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
              });
            },
          },
          {
            text: "Olympic Stadium",
            onselect: function () {
              viewer.camera.flyTo({
                destination: new Cesium.Cartesian3(
                  1267081.619536883,
                  -4290744.917138439,
                  4530941.041519919
                ),
                orientation: {
                  direction: new Cesium.Cartesian3(
                    -0.735813047510908,
                    0.6294547560338262,
                    0.24973159435503312
                  ),
                  up: new Cesium.Cartesian3(
                    -0.09796934684423217,
                    -0.4638476756625683,
                    0.88048131204549
                  ),
                },
                easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
              });
            },
          },
          {
            text: "Biosphere Museum",
            onselect: function () {
              viewer.camera.flyTo({
                destination: new Cesium.Cartesian3(
                  1269319.8408991008,
                  -4293301.826913256,
                  4527724.561372451
                ),
                orientation: {
                  direction: new Cesium.Cartesian3(
                    -0.742505030107832,
                    -0.3413204607149223,
                    -0.5763563336703441
                  ),
                  up: new Cesium.Cartesian3(
                    -0.04655102331027917,
                    -0.8320643756800384,
                    0.5527222421370013
                  ),
                },
                easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
              });
            },
          },
          {
            text: "St. Joseph's Oratory of Mount Royal",
            onselect: function () {
              viewer.camera.flyTo({
                destination: new Cesium.Cartesian3(
                  1263148.6745904868,
                  -4297262.506644816,
                  4525958.844284831
                ),
                orientation: {
                  direction: new Cesium.Cartesian3(
                    0.6550952540993403,
                    0.7551122393690295,
                    0.025606913355780074
                  ),
                  up: new Cesium.Cartesian3(
                    0.46670450470847263,
                    -0.4310758971098583,
                    0.7722437932516845
                  ),
                },
                easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
              });
            },
          },
        ]);

        // Set up checkboxes for toggling the various classification settings.
        const viewModel = {
          ground: true,
          other: true,
          buildings: true,
          low_vegetation: true,
          medium_vegetation: true,
          high_vegetation: true,
        };

        // Assign colors to each classification type.
        const pointStyles = {
          unclassified: {
            color: "color('#808080')",
            show: true,
          },
          not_awarded: {
            color: "color('#FFDEAD')",
            show: true,
          },
          ground: {
            color: "color('#FFDEAD')",
            show: true,
          },
          low_vegetation: {
            color: "color('#63FF7E')",
            show: true,
          },
          medium_vegetation: {
            color: "color('#63FF7E')",
            show: true,
          },
          high_vegetation: {
            color: "color('#22B33A')",
            show: true,
          },
          buildings: {
            color: "color('#efefef')",
            show: true,
          },
          low_point: {
            color: "color('#808080')",
            show: true,
          },
          reserved_city_diffusion: {
            color: "color('#808080')",
            show: true,
          },
        };

        const classificationDictionary = {
          not_awarded: 1,
          ground: 2,
          low_vegetation: 3,
          medium_vegetation: 4,
          high_vegetation: 5,
          buildings: 6,
          low_point: 7,
          reserved_city_diffusion: 8,
          unclassified: -1,
        };

        // This is a helper function to re-apply the styles each time the UI/checkboxes are updated.
        function applyStyle(tileset, styles) {
          const styleObject = {};
          const styleKeys = Object.keys(styles);

          styleObject.color = {
            conditions: [],
          };
          styleObject.show = {
            conditions: [],
          };

          let finalCondition;

          for (let i = 0; i < styleKeys.length; ++i) {
            const key = styleKeys[i];
            const id = classificationDictionary[key];

            const colorCondition = [
              `\${Classification} === ${id}`,
              styles[key].color,
            ];
            const showCondition = [
              `\${Classification} === ${id}`,
              styles[key].show,
            ];

            if (id === -1) {
              colorCondition[0] = true;
              showCondition[0] = true;

              finalCondition = {
                colorCondition: colorCondition,
                showCondition: showCondition,
              };
            } else {
              styleObject.color.conditions.push(colorCondition);
              styleObject.show.conditions.push(showCondition);
            }
          }

          if (Cesium.defined(finalCondition)) {
            styleObject.color.conditions.push(finalCondition.colorCondition);
            styleObject.show.conditions.push(finalCondition.showCondition);
          }

          tileset.style = new Cesium.Cesium3DTileStyle(styleObject);
        }

        // Apply an initial style.
        applyStyle(tileset, pointStyles);

        Cesium.knockout.track(viewModel);

        const toolbar = document.getElementById("toolbar");
        Cesium.knockout.applyBindings(viewModel, toolbar);

        // Set up the checkboxes.
        Cesium.knockout
          .getObservable(viewModel, "ground")
          .subscribe(function (show) {
            pointStyles.ground.show = show;
            pointStyles.not_awarded.show = show;

            applyStyle(tileset, pointStyles);
          });

        Cesium.knockout
          .getObservable(viewModel, "low_vegetation")
          .subscribe(function (show) {
            pointStyles.low_vegetation.show = show;

            applyStyle(tileset, pointStyles);
          });

        Cesium.knockout
          .getObservable(viewModel, "medium_vegetation")
          .subscribe(function (show) {
            pointStyles.medium_vegetation.show = show;

            applyStyle(tileset, pointStyles);
          });

        Cesium.knockout
          .getObservable(viewModel, "high_vegetation")
          .subscribe(function (show) {
            pointStyles.high_vegetation.show = show;

            applyStyle(tileset, pointStyles);
          });

        Cesium.knockout
          .getObservable(viewModel, "buildings")
          .subscribe(function (show) {
            pointStyles.buildings.show = show;

            applyStyle(tileset, pointStyles);
          });

        Cesium.knockout
          .getObservable(viewModel, "other")
          .subscribe(function (show) {
            pointStyles.low_point.show = show;
            pointStyles.reserved_city_diffusion.show = show;
            pointStyles.unclassified.show = show;

            applyStyle(tileset, pointStyles);
          });
        //Sandcastle_End
        Sandcastle.finishedLoading();
      }
      if (typeof Cesium !== "undefined") {
        window.startupCalled = true;
        startup(Cesium);
      }
    </script>
  </body>
</html>
